using System;
using System.Data;
using System.Data.SqlClient;
using System.Collections;

using BO = PHSRAG.Insight21.BusinessObjects;
using Utility = PHSRAG.Utility;
using ICachePolicy = PHSRAG.Insight21.Policy.ICachePolicy;
using DataAccess = PHSRAG.Utility.DataAccess;

namespace PHSRAG.Insight21.FormsManagement
{
	/// <summary>
	/// QuestionStudyPerson abstracts the notion of a person who is assigned to review specific questions
	/// </summary>
	public class QuestionStudyPerson : BO.SmartBusinessObject
	{
		#region Constants
		private const string QuestionStudyPersonKey = "QuestionStudyPersonKey_FB325F65-F8E0-4485-9727-F27B3860C99E";
		private const string QuestionStudyPersonDataTableName = "QuestionStudyPerson";
		private const string DeleteQuestionStudyPersonSProcName = "DeleteQuestionStudyPerson";
		private const string SaveQuestionStudyPersonSProcName = "SaveQuestionStudyPerson";
		private const string GetQuestionStudyPersonSProcName = "GetQuestionStudyPerson";
		private const string GetQuestionStudyPersonsForVersionSProcName = "GetQuestionStudyPersonsForVersion";

		private const string ColumnId = "Id";
		private const string ColumnVersionId = "VersionId";
		private const string ColumnRole = "Role";
		private const string ColumnItemName = "ItemName";
		private const string ColumnItemValue = "ItemValue";
		private const string ColumnValidationCategory = "ValidationCategory";
		private const string ColumnValidationMessage = "ValidationMessage";
		#endregion

		#region Instance Varibles (private)
		private int versionId;
		private string validationCategory;
		private string validationMessage;
		private string role;
		private string itemName;
		private string itemValue;
		private bool markForDeletion;
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new QuestionStudyPerson object based on the Cache Policy passed in as a parameter. 
		/// All the instance variables will be set to default values of their associated types.
		/// </summary>
		/// <param name="cachePolicy">The prevalent cache policy</param>
		public QuestionStudyPerson(ICachePolicy cachePolicy) : base(cachePolicy)
		{
		}

		/// <summary>
		/// Constructs a new QuestionStudyPerson object based on the Cache Policy passed in as a parameter. 
		/// All the instance variables will be set to the corresponding values specified in the Data Row
		/// </summary>
		/// <param name="cachePolicy">The prevalent cache policy</param>
		/// <param name="dataRow">DataRow holding the values to be assigned to instance variables</param>
		public QuestionStudyPerson(ICachePolicy cachePolicy, DataRow dataRow ) : base(cachePolicy)
		{
			PopulateDataMembers(dataRow);
		}
		#endregion

		#region Properties
		/// <summary>
		/// Gets or sets the version id of the QuestionStudyPerson object
		/// </summary>
		public int VersionId
		{
			get { return versionId; }
			set { SetDirty(ref versionId, value); }
		}
		
		
		/// <summary>
		/// Gets or sets the role of the person
		/// </summary>
		public string Role
		{
			get { return role; }
			set	{ SetDirty(ref role, value); }
		}


		/// <summary>
		/// Gets or sets the validation category
		/// </summary>
		public string ValidationCategory
		{
			get	{ return validationCategory; }
			set	{ SetDirty(ref validationCategory, value); }
		}

		
		/// <summary>
		/// Gets or sets the validation message
		/// </summary>
		public string ValidationMessage
		{
			get	{ return validationMessage;	}
			set	{ SetDirty(ref validationMessage, value); }
		}
		
		
		/// <summary>
		/// Gets or sets the name of the QuestionnaireItem to which the QuestionStudyPerson is tied
		/// </summary>
		public string ItemName
		{
			get { return itemName; }
			set { SetDirty(ref itemName, value); }
		}

		
		/// <summary>
		/// Gets or sets the value to which the QuestionnaireItem must be set for the QuestionStudyPerson to be attached by the user
		/// </summary>
		public string ItemValue
		{
			get { return itemValue; }
			set { SetDirty(ref itemValue, value); }
		}


		/// <summary>
		/// Gets or sets whether or not the QuestionStudyPerson is deleted
		/// </summary>
		public bool MarkedForDeletion
		{
			get{ return markForDeletion; }
			set{ SetDirty(ref markForDeletion, value); }
		}
		#endregion
	
		#region Caching
		/// <summary>
		/// Cache Key uniquely identifies this object within the cache.
		/// </summary>
		/// <returns>the unique string for this object.</returns>
		public override string CacheKey()
		{
			return QuestionStudyPersonKey;
		}

		/// <summary>
		/// Cache this instance using the prevalent cache policy.
		/// </summary>
		public override void Cache()
		{
			CachePolicy.Cache(QuestionStudyPersonKey, this);
		}

		/// <summary>
		/// Remove this instance from the cache using the prevalent cache policy.
		/// </summary>
		public override void UnCache()
		{
			CachePolicy.UnCache(QuestionStudyPersonKey);
		}
		#endregion

		#region Smart Business Object Methods

		/// <summary>
		/// Deletes the record represented by the object
		/// </summary>
		/// <param name="sqlTransaction">SQL transaction to use when deleting.</param>
		protected override void DeleteObject( SqlTransaction sqlTransaction)
		{
			try
			{
				DataAccess.ExecuteNonQuery( sqlTransaction.Connection, sqlTransaction, DeleteQuestionStudyPersonSProcName, DataAccess.BuildSqlParameterArray(
					"@id", SqlDbType.Int, Id
					));
			}
			catch(Exception ex)
			{
				Utility.ExceptionReport.WriteToEventLog("QuestionStudyPerson.SaveObject: Failed to save the QuestionStudyPerson object to the database", 
					ex, true, Utility.ExceptionReport.ReportType.Error);
				throw;
			}
		}


		/// <summary>
		/// Saves the state of the QuestionStudyPerson object to the database. 
		/// The stored procedure inserts a new record if the id of the object is 0, 
		/// otherwise the procedure updates the record with the matching questionstudyperson id
		/// </summary>
		/// <param name="sqlTransaction">The database context in which the underlying sql statement needs to be executed</param>
		protected override void SaveObject( SqlTransaction transaction )
		{
			try
			{
				Id = Convert.ToInt32(DataAccess.ExecuteScalar( transaction.Connection, transaction, SaveQuestionStudyPersonSProcName, DataAccess.BuildSqlParameterArray(
					"@id", SqlDbType.Int, Id,
					"@versionID", SqlDbType.Int, versionId,
					"@role", SqlDbType.VarChar, role,
					"@itemName", SqlDbType.VarChar, itemName,
					"@itemValue", SqlDbType.VarChar, itemValue,
					"@validationCategory", SqlDbType.VarChar, validationCategory,
					"@validationMessage", SqlDbType.VarChar, validationMessage
					)));

			}
			catch(Exception ex)
			{
				Utility.ExceptionReport.WriteToEventLog("QuestionStudyPerson.SaveObject: Failed to save the QuestionStudyPerson object to the database", 
					ex, true, Utility.ExceptionReport.ReportType.Error);
				throw;
			}

		}


		/// <summary>
		///  Loads the QuestionStudyPerson based on the optional Args.
		/// </summary>
		/// <param name="connectionString">Information to connect to the database</param>
		/// <param name="args">QuestionStudyPerson Id of the object to be loaded</param>
		public override void Load ( string connectionString, params object[] args )
		{
			if ( args.Length != 1 )
				throw new Exception("QuestionStudyPerson Load expects  ID");

			try
			{
				DataSet newDataSet = new DataSet();
				Utility.DataAccess.LoadDataSet(newDataSet, QuestionStudyPersonDataTableName, connectionString, GetQuestionStudyPersonSProcName, 
					Utility.DataAccess.BuildSqlParameterArray(
					"@id", SqlDbType.Int, (int)args[0]
					));
				
				DataRowCollection rows = newDataSet.Tables[QuestionStudyPersonDataTableName].Rows;
				if (rows.Count > 0)
				{
					PopulateDataMembers(rows[0]);
				}
			}
			catch( Exception e)
			{
				Utility.ExceptionReport.WriteToEventLog ("QuestionStudyPerson Load failed", e, true, Utility.ExceptionReport.ReportType.Error);
				throw;
			}
			
		}
		#endregion

		#region Static Get methods
		/// <summary>
		/// Gets all the studypersons assigned to the questionnaireversion
		/// </summary>
		/// <param name="cachePolicy">The prevalent cache policy</param>
		/// <param name="questionnaireVersionID">The id the Questionnaire Version of which the Questionnaire Items have to be fetched</param>
		/// <returns>Returns a collection of questionstudypersons</returns>
		public static ArrayList GetQuestionStudyPersonsForVersion(ICachePolicy cachePolicy, int versionId )
		{
			ArrayList studyPersonsList = new ArrayList();
			try
			{
				DataSet ds = Utility.DataAccess.GetDataSet(Utility.DataAccess.GetConnectionString(), GetQuestionStudyPersonsForVersionSProcName,
					Utility.DataAccess.BuildSqlParameterArray
					("@versionId", SqlDbType.Int, versionId));
				DataTable table = ds.Tables[0];
				foreach( DataRow row in table.Rows )
				{
					studyPersonsList.Add (new QuestionStudyPerson(cachePolicy, row));
				}
			}
			catch(Exception ex)
			{
				Utility.ExceptionReport.WriteToEventLog ("Failed to load Questionnaire Study Persons", ex, true, Utility.ExceptionReport.ReportType.Error);
				throw;
			}

			return studyPersonsList;
		}
		#endregion

		#region Private methods
		private void PopulateDataMembers(DataRow dataRow)
		{
			Id = (int)dataRow[ColumnId];
			versionId = (int)dataRow[ColumnVersionId];
			validationCategory		= (string)dataRow[ColumnValidationCategory];
			validationMessage = (string)dataRow[ColumnValidationMessage];
			role	= (string)dataRow[ColumnRole];
			itemName	= (string)dataRow[ColumnItemName];
			itemValue	= (string)dataRow[ColumnItemValue];
		}
		#endregion
	}
}
